#include "stm32f10x.h"

uint16_t AD_Values[4];

void AD_Init(void) {
    // 1. RCC
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 72MHz / 6 = 12MHz（满足不大于 14MHz）
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    // 2. GPIO
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 模拟输入
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    // 3. 多路开关
    // 指定通道放在序列1上
    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); // 55.5 CLK 周期
    ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_55Cycles5);

    // 4. AD转换器（单次、连续、模拟看门狗...)
    ADC_InitTypeDef ADC_InitStructure;
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // 工作模式（独立，双模式）
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 数据右对齐
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 软件触发
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // 连续转换
    ADC_InitStructure.ADC_ScanConvMode = ENABLE; // 扫描模式
    ADC_InitStructure.ADC_NbrOfChannel = 4; // 扫描模式下用到的通道数
    ADC_Init(ADC1, &ADC_InitStructure);

    // DMA初始化
    DMA_InitTypeDef DMA_InitStructure;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; // 外设站点的起始地址
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 外设站点的数据宽度
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 外设站点的是否自增
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)AD_Values; // 存储器的外设站点的起始地址
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // 存储器的外设站点的数据宽度
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // 存储器的外设站点的是否自增
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; // 方向(A => B)
    DMA_InitStructure.DMA_BufferSize = 4; // 缓存区大小（传输计数器）
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // 传输模式（是否自动重装）
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // 软件、硬件触发
    DMA_InitStructure.DMA_Priority = DMA_Priority_High; // 优先级
    DMA_Init(DMA1_Channel1, &DMA_InitStructure); // 此处只能是 Channel1

    // 5. 开关控制
    DMA_Cmd(DMA1_Channel1, ENABLE);
    ADC_DMACmd(ADC1, ENABLE);
    ADC_Cmd(ADC1, ENABLE);
    ADC_ResetCalibration(ADC1); // 复位校准
    while (ADC_GetResetCalibrationStatus(ADC1)); // 等待复位校准完成
    ADC_StartCalibration(ADC1); // 开始校准
    while (ADC_GetCalibrationStatus(ADC1)); // 等待校准完成
    // 软件触发转换
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
